local zip = require('zlib')
local bit = require("bit")
local _M = { _VERSION = '0.1' }
local mt = { __index = _M}

local strbyte = string.byte
local bit_lshift = bit.lshift
local bit_band = bit.band
local ngx_re_match = ngx.re.match
local zip_inflate = zip.inflate
local lrucache = require("resty.lrucache.pureffi")
local ipcache = lrucache.new(2000)
local city = require("resty.ipdb.city")
--ip查询器
local cityreader = nil
if ngx.var.ipdbpath ~= nil then
    xpcall(function()
        cityreader = city:new(io.open(ngx.var.ipdbpath, "rb"):read("*a"), true)
    end,function(err)
        ngx.log(ngx.ERR,tostring(err))        
    end)
end

if cityreader ~= nil then
    function _M.ipfind(ipaddr)
        local ret = ipcache:get(ipaddr)
        if ret == nil then
            ret = cityreader:find(ipaddr, "CN")
            ipcache:set(ipaddr,ret)
        end
        return ret
    end
else
    function _M.ipfind(ipaddr)
        return nil,'not init ipdb'
    end
end

function _M.isMatch(str,reg)
    local m = ngx_re_match(str, reg)
    if m then
        return true
    else
        return false
    end
end

function _M.hashCode(str)
    if type(str) ~= 'string' then
        return 0
    end
    local length = #str
    if length == 0 then
        return 0
    end
    local hash = 0
    local char = nil
    for i=1,length do
        char = strbyte(str,i)
        hash = bit_lshift(hash,5) - hash + char
        hash = bit_band(hash,hash)
    end
    return hash
end

local cid = 1
function _M.correlation_key()
    local id = (cid + 1) % 1073741824 -- 2^30
    cid = id
    return id..''
end

local function x_forwarded_for(forwarded_for)
    if forwarded_for then
        local ips = {}
        for ip in forwarded_for:gmatch("[^,%s]+") do
            table.insert(ips, ip)
        end
        return ips[#ips]
    end
    return nil
end

function _M.getip(forwarded_for)
    return ngx.var.http_x_real_ip or x_forwarded_for(ngx.var.http_x_forwarded_for) or ngx.var.remote_addr or '0.0.0.0'
end

function _M.uncompress(d)
	return zip_inflate()(d)
end

function _M.verifytime(data)
    if data.time > (ngx.time() + 1) * 1000 then
        data.time = ngx.time() * 1000
    end
end

return _M